/* eslint-disable no-prototype-builtins */
import config from '../config'
import md5 from 'js-md5'
import qs from 'qs'
import { codeList } from './url-white-list'
/**
 *  修改密码的singn
 * @param {String} sourceStr [加密串]
 */
export function encryptFromText (sourceStr) {
  // eslint-disable-next-line no-undef
  return Sm3Utils.encryptFromText(sourceStr)
}
/**
 *  登录的密码的加密
 * @param {String} sourceStr [加密串]
 */
export function doSm3AndSm2Encrypt (sourceStr) {
  const pubKey = config.PubKey
  // eslint-disable-next-line no-undef
  var sm2Utils = new Sm2Utils()
  // eslint-disable-next-line no-undef
  const sm3RandomPlain =
    // eslint-disable-next-line no-undef
    Sm3Utils.encryptFromText(sourceStr) +
    '|' +
    sm2Utils.randomWord(8) +
    '|' +
    sourceStr
  var sm3Sm2Plain = sm2Utils.encryptFromText(pubKey, sm3RandomPlain)
  return '{crypto}' + sm3Sm2Plain
}

/**
 *  设置请求防重放防篡改
 * @param {config} config [axios请求config]
 */
export function codeHeaders (config) {
  const requestToken = generateRequestToken()
  const uuid = requestToken.token
  const time = requestToken.timestamp
  const sign = requestToken.sign
  config.headers['X-Request-Token'] = uuid
  config.headers['X-Request-Time'] = time
  config.headers['X-Request-Sign'] = sign

  if (config.method === 'get') {
    let paramStr = ''
    if (config.url.indexOf('?') === -1) {
      for (const key in config.params) {
        if (
          // eslint-disable-next-line no-prototype-builtins
          config.params.hasOwnProperty(key) &&
          config.params[key] !== null &&
          config.params[key] !== undefined
        ) {
          paramStr += config.params[key]
        }
      }
    } else {
      const urlData = config.url.split('?')[1]
      if (urlData) {
        const params = qs.parse(urlData)
        for (const key in params) {
          if (
            // eslint-disable-next-line no-prototype-builtins
            params.hasOwnProperty(key) &&
            params[key] !== null &&
            params[key] !== undefined
          ) {
            paramStr += params[key]
          }
        }
      }
    }

    if (paramStr !== '') {
      config.headers['X-Tamper-Proofing-Sign'] = md5(paramStr)
    }
  } else if (config.data && config.method === 'post') {
    if (config.headers['Content-Type'] === 'application/json') {
      let bodyString
      if (typeof config.data === 'string') {
        bodyString = md5(config.data)
      } else {
        bodyString = md5(JSON.stringify(config.data))
      }
      config.headers['X-Tamper-Proofing-Sign'] = bodyString
    } else if (
      config.headers['Content-Type'] === 'application/x-www-form-urlencoded'
    ) {
      const fromDataJson = qs.parse(config.data)
      let str = ''
      for (const key in fromDataJson) {
        if (fromDataJson.hasOwnProperty(key)) {
          str += fromDataJson[key]
        }
      }
      if (str !== '') {
        config.headers['X-Tamper-Proofing-Sign'] = md5(str)
      }
      config.data = qs.stringify(fromDataJson)
    }
  }
  return config
}

/**
 *  设置请求防重放防篡改
 * @param {config} req [axios请求config]
 */
export function encryptBody (req) {
  let isNeedTamper = false
  for (const url of codeList) {
    if (req.url.indexOf(url) !== -1) {
      isNeedTamper = true
      break
    }
  }
  // 不需要加密的url
  if (!isNeedTamper) {
    return req
  } else {
    // 需要加密的url
    if (req.data && req.method === 'post') {
      if (
        req.headers['Content-Type'] === 'application/json' ||
        req.headers['Content-Type'] === 'application/json;charset=utf-8'
      ) {
        let dataBody
        if (typeof req.data === 'string') {
          dataBody = encodeURIComponent(req.data)
        } else {
          dataBody = encodeURIComponent(JSON.stringify(req.data))
        }

        let enPw1 = encryStr(dataBody)
        while (!getInputLenIs128Aliquot(enPw1)) {
          enPw1 = encryStr(dataBody)
        }
        req.data = enPw1
      } else if (
        req.headers['Content-Type'] === 'application/x-www-form-urlencoded'
      ) {
        const fromDataJson = qs.parse(req.data)
        for (const key in fromDataJson) {
          if (fromDataJson.hasOwnProperty(key)) {
            if (fromDataJson[key] !== '' &&
              fromDataJson[key] !== undefined &&
              fromDataJson[key] !== null) {
              // if (key === 'password') {
              const pw = encodeURIComponent(fromDataJson[key] + '')
              let enPw = encryStr(pw)
              while (!getInputLenIs128Aliquot(enPw)) {
                enPw = encryStr(pw)
              }
              fromDataJson[key] = enPw
              // } else {
              //   fromDataJson[key] = encryStr(encodeURIComponent(fromDataJson[key] + ''))
              // }
            }
          }
        }
        // req.data = qs.stringify(fromDataJson)
      }
    } else if (req.method === 'get') {
      if (req.url.indexOf('?') === -1) {
        for (const key in req.params) {
          if (req.params.hasOwnProperty(key)) {
            if (
              req.params[key] !== '' &&
              req.params[key] !== null &&
              req.params[key] !== undefined
            ) {
              const pw = encodeURIComponent(req.params[key] + '')
              let enPw1 = encryStr(pw)
              while (!getInputLenIs128Aliquot(enPw1)) {
                enPw1 = encryStr(pw)
              }
              req.params[key] = enPw1
            }
          }
        }
      } else {
        const urlData = req.url.split('?')[1]
        if (urlData) {
          const params = qs.parse(urlData)
          for (const key in params) {
            if (params.hasOwnProperty(key)) {
              if (
                params[key] !== '' &&
                params[key] !== null &&
                params[key] !== undefined
              ) {
                const pw = encodeURIComponent(params[key] + '')
                let enPw1 = encryStr(pw)
                while (!getInputLenIs128Aliquot(enPw1)) {
                  enPw1 = encryStr(pw)
                }
                params[key] = enPw1
              }
            }
          }
          req.url = req.url.split('?')[0] + '?' + qs.stringify(params)
        }
      }
    }
    return req
  }
}

// 为所有请求头增加token
function getUuid () {
  var s = []
  var hexDigits = '0123456789abcdef'
  for (var i = 0; i < 36; i++) {
    s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1)
  }
  s[14] = '4'
  s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1)
  s[8] = s[13] = s[18] = s[23] = '-'
  var uuid = s.join('')
  return uuid
}

export function generateRequestToken () {
  const token = {
    token: getUuid(),
    timestamp: new Date().getTime().toString()
  }
  // eslint-disable-next-line no-undef
  token.sign = Sm3Utils.encryptFromText(token.timestamp + ',' + token.token)
  // eslint-disable-next-line no-undef
  // token.sign = Sm3Utils.encryptFromText(token.timestamp + token.token);
  return token
}

// 加密方法
function encryStr (param) {
  var publicKey =
    'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVHneXybQdgYjgzsE9X0vFBTv0n68K57GduFiFGTDf8BHAt6PzBghTENLgi8djTrwrpLcjl14qxlqfSEYnwjPGHoshNl7OczzWm5STXPz+dOUAhAlCFScppOUg7Ywg5S00RH3S77Ii7XpuKHhh6y4zDpqGe+NUf111jvqKobuJCQIDAQAB'
  // eslint-disable-next-line no-undef
  var encrypt = new JSEncrypt()
  encrypt.setPublicKey(publicKey)
  try {
    var encryRe = encrypt.encryptLong(param)
    return encryRe
  } catch (e) {
    return '加密异常了'
  }
}

function getInputLenIs128Aliquot (string) {
  var str = b64tohex(string)
  var buf = hexToBytes(str)
  return buf.length % 128 === 0
}

// convert a base64 string to hex
var b64map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
var b64pad = '='
var BI_RM = '0123456789abcdefghijklmnopqrstuvwxyz'

function int2char (n) {
  return BI_RM.charAt(n)
}

function b64tohex (s) {
  var ret = ''
  var i
  var k = 0 // b64 state, 0-3
  var slop = 0
  for (i = 0; i < s.length; ++i) {
    if (s.charAt(i) === b64pad) {
      break
    }
    var v = b64map.indexOf(s.charAt(i))
    if (v < 0) {
      continue
    }
    if (k === 0) {
      ret += int2char(v >> 2)
      slop = v & 3
      k = 1
    } else if (k === 1) {
      ret += int2char((slop << 2) | (v >> 4))
      slop = v & 0xf
      k = 2
    } else if (k === 2) {
      ret += int2char(slop)
      ret += int2char(v >> 2)
      slop = v & 3
      k = 3
    } else {
      ret += int2char((slop << 2) | (v >> 4))
      ret += int2char(v & 0xf)
      k = 0
    }
  }
  if (k === 1) {
    ret += int2char(slop << 2)
  }
  return ret
}

// Convert a hex string to a byte array
function hexToBytes (hex) {
  for (var bytes = [], c = 0; c < hex.length; c += 2) {
    bytes.push(parseInt(hex.substr(c, 2), 16))
  }
  return bytes
}
